<?php

namespace App\Traits\User;

use App\Models\Role;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

trait HasRoles
{
    /**
     * 关联用户角色
     *
     * Date: 2018/1/25
     * @author George
     * @return mixed
     */
    public function roles(): BelongsToMany
    {
        return $this->belongsToMany(Role::class, 'user_role_pivot', 'user_id', 'role_code', 'id');
    }

    /**
     * 判断用户是否拥有指定的角色组中任意一个角色
     *
     * Date: 2018/1/25
     * @author George
     * @param array $roles
     * @return bool
     */
    public function hasRoles(array $roles = []): bool
    {
        foreach ($roles as $role) {
            if ($this->hasRole($role)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断用户是否有用指定的角色
     *
     * Date: 2018/1/25
     * @author George
     * @param string $role
     * @return bool
     */
    public function hasRole(string $role): bool
    {
        $roleCodes = $this->roleCodes();
        return $roleCodes->contains('role_code', $role);
    }

    /**
     * 获取用户的角色
     *
     * Date: 2018/1/25
     * @author George
     * @return array
     */
    public function getRolesAttribute(): array
    {
        $roles = [];
        //获取角色ID
        $roleCodes = $this->roleCodes();

        if ($roleCodes instanceof Collection && $roleCodes->isNotEmpty()) {
            //遍历角色ID获取对象信息
            foreach ($roleCodes as $role) {
                $roles[] = Cache::rememberForever("roles:{$role->role_code}", function () use ($role) {
                    return DB::table('roles')
                        ->select('code', 'name')
                        ->where('code', $role->role_code)
                        ->first();
                });
            }
        }

        return $roles;
    }

    /**
     * 获取用户所关联的角色编码
     *
     * Date: 2018/1/25
     * @author George
     * @return Collection
     */
    public function roleCodes(): Collection
    {
        //$this->id指向的是当前模型实例，也就是User的ID
        return Cache::remember("users:{$this->id}:roles", 10,function () {
            return DB::table('user_role_pivot')
                ->select('role_code')
                ->where('user_id', $this->id)->get();
        });
    }
}